package com.college.common.utils.security;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class XxhRsaUtils {

    private static final String REQ_DATE              = "reqDate";
    private static final String REQ_NO                = "reqNo";
    private static final String RESP_CODE             = "respCode";
    private static final String RESP_MSG              = "respMsg";
    private static final String RESP_NO               = "respNo";
    private static final String RESULT                = "result";

    private static final String APPKEY                = "appKey";
    private static final String BIZ_CONTENT           = "bizContent";
    private static final String TIMESTAMP             = "timestamp";
    private static final String FORMAT                = "format";
    private static final String SIGN_TYPE             = "signType";
    private static final String CHARSET               = "charset";
    private static final String VERSION               = "version";
    private static final String SIGN                  = "sign";
    private static final String CERTI_NO              = "certiNo";
    private static final String PHONE                 = "phone";
    private static final String STATUS                = "status";
    private static final String ERROR_CODE            = "errorCode";
    private static final String ERROR_MSG             = "errorMsg";

    private static final String VAL_CHARSET_DEFAULT   = "UTF-8";
    private static final String VAL_FORMAT_DEFAULT    = "json";
    private static final String VAL_SIGN_TYPE_DEFAULT = "RSA";
    private static final String VAL_SUCCESS_CODE      = "0000";
    private static final String VAL_SUCCESS_MSG       = "";
    private static final String VAL_VERSION           = "1.0.0";

    /**
     * 正式数据
     * */
    private static final String VAL_APP_KEY           = "6h4BGmj8NWatLRWM";
    /**
     * 测试数据
     * */
//    public static final String VAL_APP_KEY           = "EQXfLZdmljq8Lgvv";
    //TODO 供应商私钥
    private static String     supplierPrivateKey    = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKTdIR5uai0zGlzP\n" +
            "XOa35Yx6oO3vuGE/uhjZxxyLcPEmxrq36Xr3AFl6wIFU/LfA9XDrrv4nFD/fl6cL\n" +
            "lgsRky62g5sX53qIDRBIx8PMfqr71PBaDon60kpPyQMb7+vB8OAGttq72vJoEx7V\n" +
            "gSy94hBdE2x/toYAYWB5y2SbIbWbAgMBAAECgYA/6yAJDWQLDDIfY6IwLYJJGc5F\n" +
            "EdkZkzySn/Sro4BxbshD4kQakaNIDeiO/CVTFPPUCPx6uyoFram9cSeGORUnuu3i\n" +
            "Dzu1fv4rmZ9/DfBa76vEJGe2B1jrnr562o2JFi4tF6c+GN1kU3xBOvu5y99GQ8SF\n" +
            "rGFkEgcFCVdGTBZbAQJBANL4wsqJPfbf1k/d440cSPWD/g5Hw9vU/h78HwDkNJ2K\n" +
            "A8NRZbwqtKY+UueklTmuG5hRpkjWFgFAFNjgfix044ECQQDIDRY2hRv8rAlhwTxp\n" +
            "LpudNHdBnLIUuS4CQIcfH04fGYAgp1x5iFoKFaIYOmyUgP1P2MgRtXEzj3JVcPvw\n" +
            "bTcbAkBlyRUZ6HsX18irQc+ebi4ZHfR96UvqjOmKA3Pl1zQ3abYFDwl5blU3+8u9\n" +
            "7N7+NC0mIQaMD5YQRl2IgU7+neqBAkASFHS0erU70cSLTC6MhwTTYWGB0Yqaqt3I\n" +
            "oFJV8rtZvjFBQj7uUO9qR+g9blJP3ZSHOd1jFFXlxgocRLjQUt6PAkEAtYmNDjmO\n" +
            "98Ry3eih56pjkD2QGfACt7A4xHfJTIb4mPWe8ZuHuumbo6Jy9mk7Y9sKjar1tSj+\n" +
            "ClT57M+t5ee8ow==";
    //TODO 供应商公钥
    private static String     supplierPublicKey     = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCk3SEebmotMxpcz1zmt+WMeqDt77hhP7oY2ccci3DxJsa6t+l69wBZesCBVPy3wPVw667+JxQ/35enC5YLEZMutoObF+d6iA0QSMfDzH6q+9TwWg6J+tJKT8kDG+/rwfDgBrbau9ryaBMe1YEsveIQXRNsf7aGAGFgectkmyG1mwIDAQAB";
    private static String    zaPrivateKey          = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAO8h8JCJAMb1nd0uBkzZuWyNnL+atBzJKvIG7escD45ODf0AWKr8vSqLZ01HD86+a496CGjsae6GybK8C1MqiMSwaAsIv31nKD6U8xF607MPrD3r2lyjwUnmqBZY++R6yFNYz9ZDXcdiwCudESRsXunPJq7zfnnglCtEH+qqW8/VAgMBAAECgYEAnVc2gtMyKLbZTPuId65WG7+9oDB5S+ttD1xR1P1cmuRuvcYpkS/Eg6a/rJASLZULDpdbyzWqqaAUPD8QMINvAr3ZtkbwH5R0F/4aqOlx/5B0Okjsp3eSK2bQ8J2m/MmFKZxr6Aily7YUDdxcGcjLizsGi1KDkWS22JRufEeUNA0CQQD+g1XJ7ELqmUtrS4m4XnadB25f0g5QC0tMjoa3d9soMzK3q+Drkv8EZVpGSmSHEo1VlE7HUcnKNvK1BO5Nm4iXAkEA8IeZxaWmEcsRqiuFz8xmYGtKcYTmHgheGF4D+fnnFozSNP+3sS1lfgFQrjUkqUyZOoG1hPc6SDhGS4nbXwiscwJASO+gPR58yrgledkK3ZAMk9GWWtVajqu953GMv7UUU//gD+yspzXX6Q2WgkA9cMvrPtQig1I37sAya5e/JvRkfwJARzzCDEmdP9PW7YFqZjrxb0kXiTuFNAviYnEl2FltWb5nW48JBo6dao5VKONQclvfXfagnjriphUUrLatpB3bhQJAKRfJS6jDAIVKt7So5HOdzk4ipxgrMjG/QtZ1grO+VQectk4+tCwdJhOrr5blvdPQvFVqXBQfXuE7cibZrGs4sQ==";
    /**
     * 正式数据
     * */
    private static String    zaPublicKey           = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCezVGq7tHis9qZoc7WOXyc7SKZDLnd566Zr/NvZP81TpJiA4mdR2lP/xFBjAowEoAX33PxQiJhLIDmacdhsLH8hf5oVP63BiD2p+fNcnEUqCqNqZI4rUInydeugmksQ5sZHxVa2KjwyQqlvO1C1sw5jWqH1MaVnd92aBWFNsimwwIDAQAB";
    /**
     * 测试数据
     * */
//    private static String zaPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3J9ZOMnB4nfebdijfXXZpaDhzNq2zznEJLxmZ3jEJKbM+2G9nwSCe7jwutai758T2niJFo9YMLfCoSxgV6Tf6qJtjyKOACKWU7gfJxypzJPN3f82edN7aBjf1DjCNjccR5eRdc//WC8ijh4t4/XHhsjvDGtHxjhAjvAQpszB0eQIDAQAB";
    /**
     * 众安侧发起请求
     */
    public static void requestSignTest() {
        Map<String, Object> map = new HashMap<>();
        map.put(REQ_DATE, new Date());
        map.put(REQ_NO, "UUID1234567890");
        map.put(CERTI_NO, "MD5_CERIT_NO");
        map.put(PHONE, "18316775349");
        System.out.println("加密前的数据:" + JSONObject.toJSONString(map));
        //使用供应商的公钥加密
        String bizContent = XxhSignUtil.encryptByPublicKeyWithNoOrderForLongData(JSONObject.toJSONString(map),
                supplierPublicKey);
        Map<String, Object> req = new HashMap<>();
        req.put(APPKEY, VAL_APP_KEY);// appKey
        req.put(BIZ_CONTENT, bizContent);// 业务数据
        req.put(TIMESTAMP, DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));// 时间戳
        req.put(FORMAT, VAL_FORMAT_DEFAULT);// 格式化类型
        req.put(SIGN_TYPE, VAL_SIGN_TYPE_DEFAULT);// 签名类型
        req.put(CHARSET, VAL_CHARSET_DEFAULT);// 字节编码
        req.put(VERSION, VAL_VERSION);// API版本号
        // 的私钥加签
        String sign = XxhSignUtil.doSign(req, zaPrivateKey);
        // sign签名当成请求入参
        req.put(SIGN, sign);

        System.out.println("加密后的数据:" + JSONObject.toJSONString(req));

        //----------------------分割线--------------------------
        String getSign = String.valueOf(req.remove(SIGN));
        // 使用众安的公钥验签
        boolean verify = XxhSignUtil.rsa256CheckContent(req, getSign, zaPublicKey);
        // 使用供应商的私钥解密
        String decryptBizContent = XxhSignUtil.decryptRSAByPrivateKeyForLongData(String.valueOf(req.get(BIZ_CONTENT)),
                supplierPrivateKey);
        System.out.println("解密后的数据:" + decryptBizContent);

    }

    public static void enmain(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put(REQ_DATE,"2023-04-14 15:38:59");
        map.put(REQ_NO, "bc5bca3a-7141-4c84-9791-07900ee140f7");
        map.put(CERTI_NO, "eb19dc4f625c93a8e9d1432e0a0fb052");
        map.put(PHONE, "606ce27ecc4f7172728c89e44db51361");
        System.out.println("加密前的数据:" + JSONObject.toJSONString(map));
        //使用供应商的公钥加密
        String bizContent = XxhSignUtil.encryptByPublicKeyWithNoOrderForLongData(JSONObject.toJSONString(map),
                supplierPublicKey);
        Map<String, Object> req = new HashMap<>();
        req.put(APPKEY, VAL_APP_KEY);// appKey
        req.put(BIZ_CONTENT, bizContent);// 业务数据
        req.put(TIMESTAMP, DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));// 时间戳
        req.put(FORMAT, VAL_FORMAT_DEFAULT);// 格式化类型
        req.put(SIGN_TYPE, VAL_SIGN_TYPE_DEFAULT);// 签名类型
        req.put(CHARSET, VAL_CHARSET_DEFAULT);// 字节编码
        req.put(VERSION, VAL_VERSION);// API版本号
        // 的私钥加签
        String sign = XxhSignUtil.doSign(req, zaPrivateKey);
        // sign签名当成请求入参
        req.put(SIGN, sign);

        System.out.println("加密后的数据:" + JSONObject.toJSONString(req));

        //----------------------分割线--------------------------
        String getSign = String.valueOf(req.remove(SIGN));
        // 使用众安的公钥验签
        boolean verify = XxhSignUtil.rsa256CheckContent(req, getSign, zaPublicKey);
        // 使用供应商的私钥解密
        String decryptBizContent = XxhSignUtil.decryptRSAByPrivateKeyForLongData(String.valueOf(req.get(BIZ_CONTENT)),
                supplierPrivateKey);
        System.out.println("解密后的数据:" + decryptBizContent);
    }

    public static void main(String[] args) {
        String json = "{\n" +
                "    \"charset\": \"UTF-8\",\n" +
                "    \"bizContent\": \"0PPcLW6Uie8zPONhLnO6GvP/wuH9chBDCVy+eD5gRP21ShOszbS1odUsKi56V3JQum3PcpX4JOfxEJnMyk8O1LIJaMy/4QIR9IO2bs2ZrUlCCWqGcvDb2PTGcVS1FtzZkdN+gzSFNWcXATXoR93BmfBBLvUBtGf2KWD/1LZjsqOfsbODa7bNig4Is7nFnn7ql21zYox6SpZ2PxzjrC8QnUjAfqizOCLG97IcudzY/FxC6KQtOQtMNAESj3sVmFhw1OKjc10rjgOOsRsNSm+PdZk4c2NN6w6FiZNgV5plLXhNaTYzdPhr2VFqsZeza1DscR0QTTQHzdYZGU6ZJxnW7w==\",\n" +
                "    \"format\": \"json\",\n" +
                "    \"sign\": \"Bwj0r9+rzw0B2GT3Ctlc9Dk+JtNcH1k+4NeolSPFnfV208rbEBDzJoNsYJ/6uUsC3bAWkLna1iFAr2jTm5L/8wZuQq6TUQBNa0eNWCXVD2Kn9vfIaAgQHLENK/mAMWRJuL8+qNHESmSdQJ+6hsCnkZRCNvbOXPtWoI0bjkUwpCE=\",\n" +
                "    \"signType\": \"RSA\",\n" +
                "    \"errorCode\": \"0000\",\n" +
                "    \"timestamp\": \"20230414155611888\",\n" +
                "    \"errorMsg\": \"\"\n" +
                "}";
        Map<String, Object> req = JSON.parseObject(json);
        String getSign = String.valueOf(req.remove(SIGN));
        // 使用众安的公钥验签
        boolean verify = XxhSignUtil.rsa256CheckContent(req, getSign, zaPublicKey);
        // 使用供应商的私钥解密
        String decryptBizContent = XxhSignUtil.decryptRSAByPrivateKeyForLongData(String.valueOf(req.get(BIZ_CONTENT)),
                supplierPrivateKey);
        System.out.println("解密后的数据:" + decryptBizContent);
    }


    /**
     * 供应商返回
     */
    public static void responseSignTest() {
        Map<String, Object> result = new HashMap<>();
        result.put(CERTI_NO, "");
        result.put(PHONE, "");
        result.put(STATUS, 2);

        Map<String, Object> respInner = new HashMap<>();
        respInner.put(RESULT, result);
        respInner.put(RESP_CODE, "0000");
        respInner.put(RESP_MSG, "业务成功");
        respInner.put(RESP_NO, "UUID1234567890");
        respInner.put(REQ_NO, "UUID1234567890");

        System.out.println("加密前的数据:" + JSONObject.toJSONString(respInner));
        //使用众安的公钥加密
        String bizContent = XxhSignUtil.encryptByPublicKeyWithNoOrderForLongData(JSONObject.toJSONString(respInner),
                zaPublicKey);
        Map<String, Object> resp = new HashMap<>();
        resp.put(BIZ_CONTENT, bizContent);// 业务数据
        resp.put(CHARSET, VAL_CHARSET_DEFAULT);// 字节编码
        resp.put(FORMAT, VAL_FORMAT_DEFAULT);// 格式化类型
        resp.put(TIMESTAMP, DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));// 时间戳
        resp.put(SIGN_TYPE, VAL_SIGN_TYPE_DEFAULT);// 签名类型
        resp.put(ERROR_CODE, VAL_SUCCESS_CODE);// 错误码
        resp.put(ERROR_MSG, VAL_SUCCESS_MSG);// 错误信息
        // 供应商的私钥加签
        String sign = XxhSignUtil.doSign(resp, supplierPrivateKey);
        // sign签名当成请求入参
        resp.put(SIGN, sign);
        System.out.println("加密后的数据:" + JSONObject.toJSONString(resp));

        //----------------------分割线--------------------------

        String getSign = String.valueOf(resp.remove(SIGN));
        // 使用供应商的公钥验签
        boolean verify = XxhSignUtil.rsa256CheckContent(resp, getSign, supplierPublicKey);
        // 使用众安私钥解密
        String decryptBizContent = XxhSignUtil.decryptRSAByPrivateKeyForLongData(String.valueOf(resp.get(BIZ_CONTENT)),
                zaPrivateKey);
        System.out.println("解密后的数据:" + decryptBizContent);
    }

    public static String decryptRSAByPrivateKey(Map<String, Object> req){
        String getSign = String.valueOf(req.remove(SIGN));
        // 使用众安的公钥验签
        boolean verify = XxhSignUtil.rsa256CheckContent(req, getSign, zaPublicKey);
        // 使用供应商的私钥解密
        String decryptBizContent = XxhSignUtil.decryptRSAByPrivateKeyForLongData(String.valueOf(req.get(BIZ_CONTENT)),
                supplierPrivateKey);
        System.out.println("解密后的数据:" + decryptBizContent);
        return decryptBizContent;
    }


    public static JSONObject result(String respCode,String respMsg,String respNo,String reqNo,String phone,Boolean status,String certiNo){
        Map<String, Object> result = new HashMap<>();
        result.put(CERTI_NO, certiNo);
        result.put(PHONE, phone);
        result.put("isAllowCredit", status);
        Map<String, Object> respInner = new HashMap<>();
        respInner.put(RESULT, result);
        respInner.put(RESP_CODE, respCode);
        respInner.put(RESP_MSG, respMsg);
        respInner.put(RESP_NO, respNo);
        respInner.put(REQ_NO, reqNo);
        System.out.println("加密前的数据:" + JSONObject.toJSONString(respInner));
        //使用众安的公钥加密
        String bizContent = XxhSignUtil.encryptByPublicKeyWithNoOrderForLongData(JSONObject.toJSONString(respInner),
                zaPublicKey);
        Map<String, Object> resp = new HashMap<>();
        resp.put(BIZ_CONTENT, bizContent);// 业务数据
        resp.put(CHARSET, VAL_CHARSET_DEFAULT);// 字节编码
        resp.put(FORMAT, VAL_FORMAT_DEFAULT);// 格式化类型
        resp.put(TIMESTAMP, DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));// 时间戳
        resp.put(SIGN_TYPE, VAL_SIGN_TYPE_DEFAULT);// 签名类型
        resp.put(ERROR_CODE, VAL_SUCCESS_CODE);// 错误码
        resp.put(ERROR_MSG, VAL_SUCCESS_MSG);// 错误信息
        // 供应商的私钥加签
        String sign = XxhSignUtil.doSign(resp, supplierPrivateKey);
        // sign签名当成请求入参
        resp.put(SIGN, sign);
        System.out.println("加密后的数据:" + JSONObject.toJSONString(resp));
        return new JSONObject(resp);
    }

}
